package com.xunmall.base.interceptor;

import com.google.common.collect.Maps;
import com.xunmall.base.constants.SecurityConstants;
import com.xunmall.base.logger.AccessLogInfo;
import com.xunmall.base.logger.service.LogService;
import com.xunmall.base.util.SpringUtils;
import com.xunmall.base.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: WangYanjing
 * @Date: 2018/12/27 10:53
 * @Description: 生成并记录全局流水号
 */
@SuppressWarnings("all")
@Component
@Order(value = Ordered.LOWEST_PRECEDENCE)
@Slf4j
public class GlobalProcessIdFilter implements Filter {
    @Value("${spring.application.name:}")
    private String systemName;

    private static ThreadLocal<String> ACCESS_TOKEN = new ThreadLocal<>();
    private static ThreadLocal<String> USER_UUID = new ThreadLocal<>();

    public static String getAccessToken() {
        return ACCESS_TOKEN.get();
    }

    public static String getUserUuid() {
        return USER_UUID.get();
    }

    public static void setAccessToken(String token) {
        ACCESS_TOKEN.set(token);
    }

    public static void setUserUuid(String userUuid) {
        USER_UUID.set(userUuid);
    }

    /**
     * 初始化
     *
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        // left blank intentionally
    }

    /**
     * 过滤
     *
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain filterChain)
            throws IOException, ServletException {
        systemName = SpringUtils.getProperty("spring.application.name", "");
        HttpServletRequest request = (HttpServletRequest) req;
        long startTime = System.currentTimeMillis();

        if (!RequestMethod.OPTIONS.name().equals(((HttpServletRequest) req).getMethod())) {
            String curUrl = ((HttpServletRequest) req).getRequestURI();
            if (!(StringUtils.endsWithAny(curUrl, ".js", ".css", ".html")
                    || StringUtils.endsWithAny(curUrl, ".jpg", ".png", ".gif", ".jpeg", ".ico")
                    || StringUtils.endsWithAny(curUrl, ".woff", ".woff2"))) {
                setGlobalProcessValue((HttpServletRequest) req, (HttpServletResponse) res);
            }
        }
        AccessLogInfo logInfo = AccessLogInfo.build(this, systemName, request.getRequestURI().toString(), request.getMethod(), 0);
        filterChain.doFilter(req, res);

        long endTime = System.currentTimeMillis();
        //access log
        logInfo.setTime(endTime - startTime);
        logInfo.setRemoteIp(request.getRemoteAddr());
        log.debug(logInfo.toJson());

        //save access log
        List<String> profiles = SpringUtils.getActiveProfiles();
        if ("apigateway".equalsIgnoreCase(systemName)) {
            Map<String, String> headerMap = Maps.newHashMap();
            Collections.list(request.getHeaderNames()).stream().forEach(name -> headerMap.put(name, request.getHeader(name)));
            logInfo.setRequestHeaders(headerMap);
            LogService logService = SpringUtils.getBean(LogService.class);
            if (logService != null) {
                logService.save(logInfo);
            }
        }
    }

    private void setGlobalProcessValue(HttpServletRequest req, HttpServletResponse response) {
        String token = req.getHeader(SecurityConstants.ACCESS_TOKEN);
        if (StringUtils.isNotEmpty(token)) {
            ACCESS_TOKEN.set(token);
        }

        String userUuid = req.getHeader(SecurityConstants.USER_UID);
        if (StringUtils.isNotEmpty(userUuid)) {
            USER_UUID.set(userUuid);
        }
    }

    private String generateGlobalUuid() {
        StringBuffer gid = new StringBuffer();
        //1. 年月日
        Calendar currentTime = Calendar.getInstance();
        SimpleDateFormat formatter = new SimpleDateFormat("yyMMdd");
        gid.append(formatter.format(currentTime.getTime()));
        //2. 秒
        long sec = currentTime.get(Calendar.HOUR_OF_DAY) * 3600 + currentTime.get(Calendar.MINUTE) * 60
                + currentTime.get(Calendar.SECOND);
        NumberFormat nf = NumberFormat.getInstance();
        //设置是否使用分组
        nf.setGroupingUsed(false);
        //设置最小整数位数    
        nf.setMinimumIntegerDigits(5);
        gid.append(nf.format(sec));

        //3. 随机数
        Random r = new Random();

        int i = r.nextInt(99999999);
        //设置最小整数位数
        nf.setMinimumIntegerDigits(8);
        gid.append(nf.format(i));

        return gid.toString();
    }

    /**
     * do nothing
     */
    @Override
    public void destroy() {
        // left blank intentionally
    }
}